import React from 'react';
import { clsx } from 'clsx';

interface LoadingProps {
  size?: 'sm' | 'md' | 'lg' | 'xl';
  variant?: 'spinner' | 'dots' | 'pulse' | 'skeleton';
  color?: 'primary' | 'secondary' | 'white' | 'gray';
  text?: string;
  fullScreen?: boolean;
  className?: string;
}

const sizeClasses = {
  sm: 'w-4 h-4',
  md: 'w-6 h-6',
  lg: 'w-8 h-8',
  xl: 'w-12 h-12',
};

const colorClasses = {
  primary: 'text-blue-600',
  secondary: 'text-gray-600',
  white: 'text-white',
  gray: 'text-gray-400',
};

// 旋转加载器
const Spinner: React.FC<{ size: string; color: string }> = ({
  size,
  color,
}) => (
  <svg
    className={clsx('animate-spin', size, color)}
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    viewBox="0 0 24 24"
  >
    <circle
      className="opacity-25"
      cx="12"
      cy="12"
      r="10"
      stroke="currentColor"
      strokeWidth="4"
    />
    <path
      className="opacity-75"
      fill="currentColor"
      d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
    />
  </svg>
);

// 点状加载器
const Dots: React.FC<{ size: string; color: string }> = ({ size, color }) => (
  <div className={clsx('flex space-x-1', color)}>
    {[0, 1, 2].map(i => (
      <div
        key={i}
        className={clsx(
          'animate-pulse rounded-full bg-current',
          size === 'h-4 w-4'
            ? 'h-1 w-1'
            : size === 'h-6 w-6'
              ? 'h-1.5 w-1.5'
              : size === 'h-8 w-8'
                ? 'h-2 w-2'
                : 'h-3 w-3'
        )}
        style={{
          animationDelay: `${i * 0.2}s`,
          animationDuration: '1s',
        }}
      />
    ))}
  </div>
);

// 脉冲加载器
const Pulse: React.FC<{ size: string; color: string }> = ({ size, color }) => (
  <div
    className={clsx(
      'animate-pulse rounded-full bg-current',
      size,
      color,
      'opacity-75'
    )}
  />
);

// 骨架屏加载器
const Skeleton: React.FC<{ className?: string }> = ({ className }) => (
  <div
    className={clsx(
      'animate-pulse rounded bg-gray-300 dark:bg-gray-700',
      className
    )}
  />
);

export const Loading: React.FC<LoadingProps> = ({
  size = 'md',
  variant = 'spinner',
  color = 'primary',
  text,
  fullScreen = false,
  className,
}) => {
  const sizeClass = sizeClasses[size];
  const colorClass = colorClasses[color];

  const renderLoader = () => {
    switch (variant) {
      case 'dots':
        return <Dots size={sizeClass} color={colorClass} />;
      case 'pulse':
        return <Pulse size={sizeClass} color={colorClass} />;
      case 'skeleton':
        return (
          <Skeleton
            className={clsx(sizeClass, 'bg-gray-300 dark:bg-gray-700')}
          />
        );
      default:
        return <Spinner size={sizeClass} color={colorClass} />;
    }
  };

  const content = (
    <div
      className={clsx('flex flex-col items-center justify-center', className)}
    >
      {renderLoader()}
      {text && <p className={clsx('mt-2 text-sm', colorClass)}>{text}</p>}
    </div>
  );

  if (fullScreen) {
    return (
      <div className="fixed inset-0 z-50 flex items-center justify-center bg-white bg-opacity-75 dark:bg-gray-900 dark:bg-opacity-75">
        {content}
      </div>
    );
  }

  return content;
};

// 内联加载器
export const InlineLoading: React.FC<{
  size?: 'sm' | 'md';
  className?: string;
}> = ({ size = 'sm', className }) => (
  <Loading
    size={size}
    variant="spinner"
    color="gray"
    className={clsx('inline-flex', className)}
  />
);

// 按钮加载器
export const ButtonLoading: React.FC<{
  size?: 'sm' | 'md';
  color?: 'primary' | 'white';
}> = ({ size = 'sm', color = 'white' }) => (
  <Loading size={size} variant="spinner" color={color} className="mr-2" />
);

// 页面加载器
export const PageLoading: React.FC<{
  text?: string;
}> = ({ text = '加载中...' }) => (
  <Loading size="lg" variant="spinner" color="primary" text={text} fullScreen />
);

// 卡片加载器
export const CardLoading: React.FC<{
  lines?: number;
  className?: string;
}> = ({ lines = 3, className }) => (
  <div className={clsx('space-y-3', className)}>
    <Skeleton className="h-4 w-3/4" />
    {Array.from({ length: lines - 1 }).map((_, i) => (
      <Skeleton key={i} className="h-4 w-full" />
    ))}
  </div>
);

// 表格加载器
export const TableLoading: React.FC<{
  rows?: number;
  columns?: number;
}> = ({ rows = 5, columns = 4 }) => (
  <div className="space-y-2">
    {Array.from({ length: rows }).map((_, rowIndex) => (
      <div key={rowIndex} className="flex space-x-4">
        {Array.from({ length: columns }).map((_, colIndex) => (
          <Skeleton key={colIndex} className="h-4 flex-1" />
        ))}
      </div>
    ))}
  </div>
);

// 头像加载器
export const AvatarLoading: React.FC<{
  size?: 'sm' | 'md' | 'lg';
}> = ({ size = 'md' }) => {
  const sizeClass = {
    sm: 'w-8 h-8',
    md: 'w-12 h-12',
    lg: 'w-16 h-16',
  }[size];

  return <Skeleton className={clsx('rounded-full', sizeClass)} />;
};

// 文本加载器
export const TextLoading: React.FC<{
  lines?: number;
  className?: string;
}> = ({ lines = 1, className }) => (
  <div className={clsx('space-y-2', className)}>
    {Array.from({ length: lines }).map((_, i) => (
      <Skeleton
        key={i}
        className={clsx('h-4', i === lines - 1 ? 'w-2/3' : 'w-full')}
      />
    ))}
  </div>
);

// 图片加载器
export const ImageLoading: React.FC<{
  width?: string;
  height?: string;
  className?: string;
}> = ({ width = 'w-full', height = 'h-48', className }) => (
  <Skeleton className={clsx(width, height, 'rounded-lg', className)} />
);

// 加载状态 Hook
export function useLoadingState(initialState = false) {
  const [loading, setLoading] = React.useState(initialState);

  const withLoading = React.useCallback(
    async <T,>(asyncFn: () => Promise<T>): Promise<T> => {
      setLoading(true);
      try {
        const result = await asyncFn();
        return result;
      } finally {
        setLoading(false);
      }
    },
    []
  );

  return {
    loading,
    setLoading,
    withLoading,
  };
}

export default Loading;
